/**
 * Copyright (c) [2025] [AGIROS] 
 * [travoddsgen] is licensed under Mulan PSL v2. 
 * You can use this software according to the terms and conditions of the Mulan PSL v2. 
 * You may obtain a copy of Mulan PSL v2 at: 
 *          http://license.coscl.org.cn/MulanPSL2 
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 
 * See the Mulan PSL v2 for more details.
 */ 

#include "CLangTypeNameVisitor.h"

void CLangTypeNameVisitor::visit(StructForwardDclNode& node) {
    // 结构体名
    std::string structName = modulePrefix() + *node.identifier_;
    forwardDeclare_[structName] = "struct";
}

void CLangTypeNameVisitor::visit(BaseTypeNode& node) {
    std::string typeName;
    switch (node.type_) {
        case BaseTypeNode::Type::BOOLEAN:
            typeName = "DDS_Boolean";
            break;
        case BaseTypeNode::Type::CHAR:
            typeName = "DDS_Char";
            break;
        case BaseTypeNode::Type::WCHAR:
            typeName = "DDS_WChar";
            break;
        case BaseTypeNode::Type::UCHAR:
            typeName = "DDS_UChar";
            break;
        case BaseTypeNode::Type::SHORT:
            typeName = "DDS_Short";
            break;
        case BaseTypeNode::Type::USHORT:
            typeName = "DDS_UShort";
            break;
        case BaseTypeNode::Type::LONG:
            typeName = "DDS_Long";
            break;
        case BaseTypeNode::Type::ULONG:
            typeName = "DDS_ULong";
            break;
        case BaseTypeNode::Type::LONGLONG:
            typeName = "DDS_LongLong";
            break;
        case BaseTypeNode::Type::ULONGLONG:
            typeName = "DDS_ULongLong";
            break;
        case BaseTypeNode::Type::FLOAT:
            typeName = "DDS_Float";
            break;
        case BaseTypeNode::Type::DOUBLE:
            typeName = "DDS_Double";
            break;
        case BaseTypeNode::Type::LONG_DOUBLE:
            typeName = "DDS_LongDouble";
            break;
        default:
            break;
    }
    nameMap_[&node] = typeName;
}

void CLangTypeNameVisitor::visit(SequenceTypeNode& node) {
    if (node.size_) {
        node.size_->accept(*this);
    }
    // 递归访问子节点
    node.type_->accept(*this);
    std::string eleTypeName = findName(node.type_);
    nameMap_[&node] = eleTypeName + "Sequence";
}

void CLangTypeNameVisitor::visit(StringTypeNode& node) {
    if (node.size_) {
        node.size_->accept(*this);
    }
    nameMap_[&node] = "DDS_CString";
}

void CLangTypeNameVisitor::visit(WideStringTypeNode& node) {
    if (node.size_) {
        node.size_->accept(*this);
    }
    nameMap_[&node] = "DDS_CWString";
}

void CLangTypeNameVisitor::visit(FixedPtTypeNode& node) {
    std::string typeName = "DDS_Fixed";
    nameMap_[&node] = typeName;
}

void CLangTypeNameVisitor::visit(MapTypeNode& node) {
    if (node.size_) {
        node.size_->accept(*this);
    }
    // 依次访问子节点
    node.keyType_->accept(*this);
    node.valueType_->accept(*this);
    std::string keyTypeName = findName(node.keyType_);
    std::string valueTypeName = findName(node.valueType_);
    nameMap_[&node] = keyTypeName + "" + valueTypeName + "Map";
}

std::string CLangTypeNameVisitor::scopedName(ScopedNameNode* node, unsigned int length) {
    std::string scopedName = "";
    unsigned int nameLength = node->components_.size() > length ? length : node->components_.size();
    for (size_t i = 0; i < nameLength; ++i) {
        scopedName += *node->components_[i];
        if (i != nameLength - 1) {
            scopedName += "_";
        }
    }
    return scopedName;
}

std::string CLangTypeNameVisitor::modulePrefix() {
    std::string prefix;
    for (auto& module : moduleStack_) {
        prefix += module + "_";
    }
    return prefix;
}
